package cn.com.blueInfo.autoCode;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
import com.baomidou.mybatisplus.generator.config.builder.CustomFile;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.baomidou.mybatisplus.generator.keywords.MySqlKeyWordsHandler;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;

import java.util.*;

public class MybatisPlusAutoCode {

    // ========================= 核心配置区（根据项目需求修改） =========================
    /** 数据库配置 */
    private static final DbConfig DB_CONFIG = new DbConfig(
            "jdbc:mysql://localhost:3306/haiyuan_dev?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai",
            "root",
            "MyMemory19910516",
            "com.mysql.cj.jdbc.Driver"
    );

    /** 项目路径配置 */
    private static final ProjectConfig PROJECT_CONFIG = new ProjectConfig(
            "D:\\Development Program\\ProjectCode_idea\\LanxiPavilion\\LanxiPavilion-parent\\LanxiPavilion-AutoCode",
            "/src/main/java",
            "/src/main/resources/mybatis",
            "cn.com.blueInfo.autoCode",  // 基础包名
            "sys",                       // 模块名
            "/templates"                 // 模板路径（相对于resources）
    );

    /** 生成配置 */
    private static final GeneratorConfig GEN_CONFIG = new GeneratorConfig(
            new String[]{"^mc_sys_.*"},  // 生成的表名（支持正则）
            "mc_sys_",                   // 表名前缀（生成类名时会去除）
            "suxch"                      // 作者名
    );
    // ==============================================================================

    public static void main(String[] args) {
        // 初始化代码生成器
        FastAutoGenerator generator = FastAutoGenerator.create(
                DB_CONFIG.getUrl(),
                DB_CONFIG.getUsername(),
                DB_CONFIG.getPassword()
        );

        // 配置数据源
        configureDataSource(generator);

        // 配置全局参数
        configureGlobal(generator);

        // 配置包结构
        configurePackage(generator);

        // 配置生成策略
        configureStrategy(generator);

        // 配置自定义注入（Repository层）
        configureInjection(generator);

        // 执行生成
        /*generator.templateEngine(new FreemarkerTemplateEngine() {
            public @NotNull String templateFilePath(@NotNull String filePath) {
                ConfigBuilder config = this.getConfigBuilder();
                List<TableInfo> tableInfoList = config.getTableInfoList();
                tableInfoList.forEach((tableInfo) -> {
                    Map<String, Object> objectMap = this.getObjectMap(config, tableInfo);
                    Optional.ofNullable(config.getInjectionConfig()).ifPresent((t) -> {
                        t.beforeOutputFile(tableInfo, objectMap);
                        this.outputCustomFile(t.getCustomFiles(), tableInfo, objectMap);
                    });
                    System.out.println(JSON.toJSONString(tableInfo));
                    objectMap.remove("config");
                    System.out.println(JSON.toJSONString(objectMap));
                    this.outputEntity(tableInfo, objectMap);
                    this.outputMapper(tableInfo, objectMap);
                    this.outputService(tableInfo, objectMap);
                    this.outputController(tableInfo, objectMap);
                });
                return filePath + ".ftl";
            }
        }).execute();*/
        generator.templateEngine(new FreemarkerTemplateEngine()).execute();
    }

    /**
     * 配置数据源
     */
    private static void configureDataSource(FastAutoGenerator generator) {
        generator.dataSourceConfig(builder -> builder
                .schema("mybatis-plus")
                .driverClassName(DB_CONFIG.getDriver())
                .keyWordsHandler(new MySqlKeyWordsHandler())
        );
    }

    /**
     * 配置全局参数
     */
    private static void configureGlobal(FastAutoGenerator generator) {
        generator.globalConfig(builder -> builder
                .disableOpenDir()  // 关闭自动打开目录
                .outputDir(PROJECT_CONFIG.getJavaOutputDir())  // Java文件输出目录
                .author(GEN_CONFIG.getAuthor())  // 作者名
                .enableSwagger()  // 开启Swagger注解
                .dateType(DateType.TIME_PACK)  // 时间类型使用java.time包
                .commentDate("yyyy-MM-dd HH:mm:ss")  // 注释日期格式
        );
    }

    /**
     * 配置包结构
     */
    private static void configurePackage(FastAutoGenerator generator) {
        generator.packageConfig(builder -> builder
                .parent(PROJECT_CONFIG.getBasePackage())  // 基础包名
                .moduleName(PROJECT_CONFIG.getModuleName())  // 模块名
                .entity("entity")          // 实体类包名
                .mapper("mapper")          // Mapper接口包名
                .service("service")        // Service接口包名
                .serviceImpl("service.impl")  // Service实现类包名
                .controller("controller")  // Controller包名
                .xml("mapper.xml")         // MapperXML包名
                // 配置XML输出路径
                .pathInfo(Collections.singletonMap(
                        OutputFile.xml,
                        PROJECT_CONFIG.getXmlOutputDir()
                ))
        );
    }

    /**
     * 配置生成策略（各层代码生成规则）
     */
    private static void configureStrategy(FastAutoGenerator generator) {
        generator.strategyConfig(builder -> builder
                .addInclude(GEN_CONFIG.getTables())  // 指定生成的表
                .addTablePrefix(GEN_CONFIG.getTablePrefix())  // 去除表名前缀

                // 实体类策略
                .entityBuilder()
                .formatFileName("%s")  // 类名格式（去除前缀后的表名）
                .javaTemplate(PROJECT_CONFIG.getTemplatePath() + "/entity.java")  // 实体类模板

                // Controller策略
                .controllerBuilder()
                .template(PROJECT_CONFIG.getTemplatePath() + "/controller.java")  // Controller模板
                .formatFileName("%sController")  // 控制器类名格式

                // Service策略
                .serviceBuilder()
                .serviceTemplate(PROJECT_CONFIG.getTemplatePath() + "/service.java")  // Service接口模板
                .serviceImplTemplate(PROJECT_CONFIG.getTemplatePath() + "/serviceImpl.java")  // Service实现类模板
                .formatServiceFileName("%sService")  // Service接口名格式
                .formatServiceImplFileName("%sServiceImpl")  // Service实现类名格式

                // Mapper策略
                .mapperBuilder()
                .mapperTemplate(PROJECT_CONFIG.getTemplatePath() + "/mapper.java")  // Mapper接口模板
                .mapperXmlTemplate(PROJECT_CONFIG.getTemplatePath() + "/mapper.xml")  // MapperXML模板
                .formatMapperFileName("%sMapper")  // Mapper接口名格式
                .formatXmlFileName("%sMapper")  // MapperXML文件名格式
        );
    }

    /**
     * 配置自定义注入（生成Repository层代码）
     */
    private static void configureInjection(FastAutoGenerator generator) {
        // 自定义参数（传递给模板）
        HashMap<String, Object> customMap = new HashMap<>();
        customMap.put("repositoryPackage", PROJECT_CONFIG.getRepositoryPackage());
        customMap.put("repositoryImplPackage", PROJECT_CONFIG.getRepositoryImplPackage());
        customMap.put("dtoPackage", PROJECT_CONFIG.getDtoPackage());
        customMap.put("voPackage", PROJECT_CONFIG.getVoPackage());
        customMap.put("convertPackage", PROJECT_CONFIG.getConvertPackage());

        // 自定义文件配置（Repository层）
        List<CustomFile> customFiles = new ArrayList<>();

        // 添加Repository接口
        customFiles.add(new CustomFile.Builder()
                .packageName("repository")  // 目标包名（相对于基础包）
                .fileName("Repository.java")  // 文件名前缀
                .templatePath(PROJECT_CONFIG.getTemplatePath() + "/repository.java.ftl")  // 模板路径
                .formatNameFunction(TableInfo::getEntityName)  // 用实体类名拼接文件名
                .build()
        );

        // 添加Repository实现类
        customFiles.add(new CustomFile.Builder()
                .packageName("repository.impl")  // 目标包名（相对于基础包）
                .fileName("RepositoryImpl.java")  // 文件名前缀
                .templatePath(PROJECT_CONFIG.getTemplatePath() + "/repositoryImpl.java.ftl")  // 模板路径
                .formatNameFunction(TableInfo::getEntityName)  // 用实体类名拼接文件名
                .build()
        );

        // 添加DTO实体类
        customFiles.add(new CustomFile.Builder()
                .packageName("request")  // 目标包名（相对于基础包）
                .fileName("DTO.java")  // 文件名前缀
                .templatePath(PROJECT_CONFIG.getTemplatePath() + "/dto.java.ftl")  // 模板路径
                .formatNameFunction(TableInfo::getEntityName)  // 用实体类名拼接文件名
                .build()
        );

        // 添加VO实体类
        customFiles.add(new CustomFile.Builder()
                .packageName("response")  // 目标包名（相对于基础包）
                .fileName("VO.java")  // 文件名前缀
                .templatePath(PROJECT_CONFIG.getTemplatePath() + "/vo.java.ftl")  // 模板路径
                .formatNameFunction(TableInfo::getEntityName)  // 用实体类名拼接文件名
                .build()
        );

        // 添加VO实体类
        customFiles.add(new CustomFile.Builder()
                .packageName("convert")  // 目标包名（相对于基础包）
                .fileName("Convert.java")  // 文件名前缀
                .templatePath(PROJECT_CONFIG.getTemplatePath() + "/convert.java.ftl")  // 模板路径
                .formatNameFunction(TableInfo::getEntityName)  // 用实体类名拼接文件名
                .build()
        );

        generator.injectionConfig(ic -> ic
                .customMap(customMap)
                .customFile(customFiles)
        );
    }

    // ========================= 配置模型类（JDK 8 兼容：静态内部类 + getter） =========================
    /**
     * 数据库配置模型（JDK 8 兼容版）
     */
    @Getter
    @AllArgsConstructor
    private static class DbConfig {
        private final String url;
        private final String username;
        private final String password;
        private final String driver;
    }

    /**
     * 项目路径配置模型（JDK 8 兼容版）
     */
    @Getter
    @AllArgsConstructor
    private static class ProjectConfig {
        private final String basePath;       // 项目根路径
        private final String javaPath;       // Java源码相对路径
        private final String xmlPath;        // XML相对路径
        private final String basePackage;    // 基础包名
        private final String moduleName;     // 模块名
        private final String templatePath;   // 模板相对路径

        public String getJavaOutputDir() {
            return basePath + javaPath;
        }

        public String getXmlOutputDir() {
            return basePath + xmlPath + "/" + moduleName;
        }

        public String getRepositoryPackage() {
            return getCurrentModuleName() + "repository";
        }

        public String getRepositoryImplPackage() {
            return getCurrentModuleName() + "repository.impl";
        }

        public String getDtoPackage() {
            return getCurrentModuleName() + "request";
        }

        public String getVoPackage() {
            return getCurrentModuleName() + "response";
        }

        public String getConvertPackage() {
            return getCurrentModuleName() + "convert";
        }

        private String getCurrentModuleName() {
            return basePackage + "." + moduleName + ".";
        }

    }

    /**
     * 生成规则配置模型（JDK 8 兼容版）
     */
    @Getter
    @AllArgsConstructor
    private static class GeneratorConfig {
        private final String[] tables;       // 要生成的表名
        private final String tablePrefix;    // 表名前缀
        private final String author;         // 作者名
    }
}
